package com.snoob.bffAdmin.wConfig.Intercept;

import com.snoob.bffAdmin.wConfig.Intercept.auth.Auth;
import com.snoob.bffAdmin.wConfig.properties.SysProperties;
import com.snoob.bffAdmin.wConfig.redis.RedissonSingleService;
import com.snoob.springcloudalibaba.base.BaseException;
import com.snoob.springcloudalibaba.base.BaseLoginUserInfo;
import com.snoob.springcloudalibaba.constant.SysKeyConstant;
import com.snoob.springcloudalibaba.enums.SysKeyEnum;
import com.snoob.springcloudalibaba.enums.SysStateEnum;
import com.snoob.springcloudalibaba.util.jwt.JwtUtil;
import com.snoob.springcloudalibaba.util.StrUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.MessageFormat;

/**
 * @描述 Token拦截器，需要在WebMvcConfig中配置
 * @作者 lixing
 * @日期 2021/6/9 13:56
 */
@Component
public class AuthIntercept implements HandlerInterceptor {
    @Resource
    private RedissonSingleService<String> redissonSingleServiceStr;

    @Resource
    private SysProperties sysProperties;

    public AuthIntercept(RedissonSingleService<String> redissonSingleServiceStr, SysProperties sysProperties) {
        this.redissonSingleServiceStr = redissonSingleServiceStr;
        this.sysProperties = sysProperties;
    }

    /**
     * @描述 前置拦截
     * @作者 lixing
     * @日期 2021/6/9 13:58
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        //        // 白名单列表
        //        //   /login/**      匹配 /login 开头
        //        //   /trip/api/*x   匹配 /trip/api/x，/trip/api/ax，/trip/api/abx ；但不匹配 /trip/abc/x
        //        //   /trip/a/a?x    匹配 /trip/a/abx；但不匹配 /trip/a/ax，/trip/a/abcx
        //        //   /**/api/alie   匹配 /trip/api/alie，/trip/dax/api/alie；但不匹配 /trip/a/api
        //        //   /**/*.htmlm    匹配所有以.htmlm结尾的路径
        //        List<String> whiteUrlList = sysProperties.getWhiteUrlList();
        //        // 当前请求的地址，格式：
        //        // http://127.0.0.1:8801/bff/auth/login/userLogin
        //        String reqPath = RequestUtil.getRequestUrl(request);
        //        PathMatcher pathMatcher = new AntPathMatcher();
        //        for (String whiteUrl : whiteUrlList) {
        //            if (StrUtil.isEffective(whiteUrl) && pathMatcher.match(whiteUrl.trim(), reqPath)) {
        //                return true;
        //            }
        //        }
        // 获取注解对象
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        Auth auth = handlerMethod.getMethodAnnotation(Auth.class);
        if (null != auth ) {
            // 获取注解中的参数
            boolean isCheck = auth.isCheck();
            if (isCheck) {
                String token = request.getHeader("Authorization");
                if (!StrUtil.isEffective(token)) {
                    throw new BaseException(SysKeyEnum.TOKEN.getDescribe());
                }
                try {
                    BaseLoginUserInfo baseLoginUserInfo = JwtUtil.verifyJwtForHs256(token);
                    // redis中校验登录状态 SpringCloudAlibabaDemo:login:version:admin
                    String versionKey = MessageFormat.format(SysKeyEnum.LOGIN_USER_VERSION.getKey(), SysKeyConstant.PROJECTNAME, baseLoginUserInfo.getUserAccount());
                    if (!redissonSingleServiceStr.isExists(versionKey)) {
                        // redis中没有当前key，则表示登录超时了，需要重写登录
                        throw new BaseException(SysStateEnum.RESPONSE_STATUS_FALSE_TOKEN_TIMEOUT.getValue(), SysStateEnum.RESPONSE_STATUS_FALSE_TOKEN_TIMEOUT.getDescribe());
                    } else {
                        // 判断当前的version和redis中的version是否一致，不一致则表示当前已经有人登录，需要重新登录
                        String tokenVersion = redissonSingleServiceStr.getKey(versionKey);
                        if (!baseLoginUserInfo.getVersion().equals(tokenVersion)) {
                            throw new BaseException(SysStateEnum.RESPONSE_STATUS_FALSE_TOKEN_EXISTS.getValue(), SysStateEnum.RESPONSE_STATUS_FALSE_TOKEN_EXISTS.getDescribe());
                        }
                    }
                    //
                    request.setAttribute(SysKeyEnum.LOGIN_USERINFO.getKey(), baseLoginUserInfo);
                } catch (Exception e) {
                    throw new BaseException(e.getMessage());
                }
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
